import UUID from 'uuid';
import SqlString from 'sqlstring';
import { getPool, exesql, insertTable } from '../database/db';
import { bindDeviceToBaidu } from '../controllers/baidu_api';
import {
    getWechatIdBySn,
} from '../controllers/wx_token';

/**
 *第一次绑定设备
 *
 * @export
 * @param {扫描到的设备id} device_id
 * @param {微信用户id} openid
 * @param {昵称} nickName
 * @param {客户端ip} ip
 * @param {回调} cb
 * @returns
 */
export async function firstBindDevice(device_id, openid, nickName, ip, cb) {
    try {
        const sql = 'SELECT `uuid`,`token`,`access_token` FROM `device_uuid_list` WHERE `device_id`= ? LIMIT 1; ';
        const { err, result } = await exesql(sql, [device_id]);
        if (err) {
            cb(err);
            return;
        }
        if (result.length === 0) {
            cb(`device_uuid_list 不存在的设备:${device_id}`);
            return;
        }
        // 查找 wechat_id
        const wecahtId = getWechatIdBySn(device_id);
        if (wecahtId === 0) {
            cb(`查询不到对应的公众号信息:${device_id}`);
            return;
        }

        // 添加一条设备记录
        const uuid = result[0].uuid;
        const accessToken = result[0].access_token;
        const iResult = await insertTable({
            ip: ip,
            sn: device_id,
            nick_name: nickName,
            uuid: uuid,
            wechat_id: wecahtId
        }, 'device');
        if (iResult.err) {
            cb(iResult.err);
            return;
        }
        console.log(`第一次绑定该设备:${device_id},激活设备,bindToken:${result[0].token}, access_token:${accessToken}`);
        const bindResult = await bindDeviceToBaidu(uuid, result[0].token, accessToken);
        if (bindResult.err || bindResult.result === '') {
            cb(`${uuid}, bindToken:${bindResult.result[0].token}, ${accessToken} 激活百度失败,${err},result:${bindResult.result}`);
            return;
        }
        const retCode = parseInt(bindResult.result.code, 10);
        if (retCode === 0 || retCode === 1210) {
            const err = await initDeviceAndOpenid(device_id, openid, uuid);
            cb(err);
        } else {
            cb(JSON.stringify(bindResult.result));
        }
    } catch (err) {
        cb(err);
    }
}


/**
 * 删除绑定的用户
 * @param {} connection
 * @param {*} openid
 * @returns
 */
function removeOpenid(connection, openid) {
    const sql = SqlString.format('DELETE FROM `device_openid` WHERE `open_id` = ?', [openid])
    return new Promise(function (resolve, reject) {
        connection.query(sql, function (err, rows, fields) {
            let dic = {};
            if (err) {
                Object.assign(dic, { err: new Error('err=' + err), result: null })
            } else {
                Object.assign(dic, { err: null, result: rows })
            }
            return resolve(dic);
        })
    })
}

/**
 *添加用户
 * @param {*} connection
 * @param {*} data
 * @returns
 */
function addOpenid(connection, data) {
    const sql = SqlString.format('INSERT INTO `device_openid` SET ? ;', data);
    return new Promise(function (resolve, reject) {
        connection.query(sql, function (err, rows, fields) {
            let dic = {};
            if (err) {
                Object.assign(dic, { err: new Error('err=' + err), result: null })
            } else {
                Object.assign(dic, { err: null, result: rows })
            }
            return resolve(dic);
        })
    })
}

/**
 * 初始化教材
 * @param {设备的uuid} uuid 
 */
function initDeviceAlbum(connection, uuid) {
    const sql = SqlString.format('call `init_device_album`(?)', [uuid]);
    return new Promise(function (resolve, reject) {
        connection.query(sql, function (err, rows, fields) {
            let dic = {};
            if (err) {
                Object.assign(dic, { err: new Error('err=' + err), result: null })
            } else {
                Object.assign(dic, { err: null, result: rows })
            }
            return resolve(dic);
        })
    })
}

// 重置绑定设备用户
async function resetOpenid(connection, device_id, openid, uuid, cb) {
    console.log(`device_id:${device_id}, openid:${openid}`);
    try {
        const { err } = await removeOpenid(connection, openid);
        if (err) {
            console.log(`removeOpenid:`, err);
            cb(err);
            return;
        }
        const iResult = await addOpenid(connection, { device_sn: device_id, open_id: openid });
        if (iResult.err) {
            console.log(`addOpenid:`, iResult.err);
            cb(iResult.err);
            return;
        }

        // 初始化专辑
        const data = await initDeviceAlbum(connection, uuid);
        cb(data.err);

    } catch (err) {
        console.log(`resetOpenid:`, err);
        cb(err);
    }
}

// ###############################################

/**
 * 多次绑定
 * @param {设备序列号} device_id 
 * @param {微信用户id} openid 
 * @param {查询到的device_uuid_list对象} device 
 * @param {回调} cb 
 */
export async function multipleBindDevice(device_id, openid, cb) {

    try {
        const sql = 'SELECT `uuid`,`token`,`access_token` FROM `device_uuid_list` WHERE `device_id`= ? LIMIT 1; ';
        const { err, result } = await exesql(sql, [device_id]);
        if (err) {
            cb(err);
            return;
        }
        if (result.length === 0) {
            cb(`device_uuid_list 不存在的设备:${device_id}`);
            return;
        }
        const uuid = result[0].uuid;
        const bindToken = result[0].token;
        const accessToken = result[0].access_token;

        const ret = await bindDeviceToBaidu(uuid, bindToken, accessToken);
        if (ret.err || ret.result === '') {
            cb(`${uuid}, bindToken:${bindToken}, ${accessToken} 激活百度失败,${ret.err.stack},result:${ret.result}`);
            return;
        }
        const retCode = parseInt(ret.result.code, 10);
        if (retCode === 0 || retCode === 1210) {
            const err = await initDeviceAndOpenid(device_id, openid, uuid);
            cb(err);
        } else {
            cb(JSON.stringify(result));
        }

    } catch (error) {
        cb(error);
    }
}


/**
 * @param {设备序序列号} device_id 
 * @param {微信用户id} openid 
 * @param {设备的uuid} uuid 
 */
function initDeviceAndOpenid(device_id, openid, uuid) {
    return new Promise(function (resolve, reject) {
        getPool().getConnection(function (err, connection) {
            if (err) {
                console.log(`获取mysql连接对象失败:`, err);
                return resolve(err);
            }
            // 事务处理
            connection.beginTransaction(function (err) {
                if (err) {
                    console.log(`begin Transaction 失败:`, err);
                    return resolve(err);
                }
                resetOpenid(connection, device_id, openid, uuid, function (err) {
                    if (err) {
                        connection.rollback(function (e) {
                            connection.release();
                            return resolve(err);
                        });
                    } else {
                        connection.commit(function (error, info) {
                            if (error) {
                                console.log('commit transaction:' + error);
                                connection.rollback(function (err) {
                                    connection.release();
                                    return resolve(error);
                                });
                            } else {
                                connection.release();
                                return resolve(null);
                            }
                        });
                    }
                });
            });
        });
    });
}
